package com.base.cn.platform.os.service.classes.topic;

import com.base.cn.platform.os.common.classes.ClassesStatisticsEnum;
import com.base.cn.platform.os.common.classes.topic.ClassesTopicClassifyEnum;
import com.base.cn.platform.os.common.mybatis.BaseBiz;
import com.base.cn.platform.os.common.mybatis.Pagination;
import com.base.cn.platform.os.common.utils.DataUtil;
import com.base.cn.platform.os.common.utils.ObjectUtils;
import com.base.cn.platform.os.common.utils.StringUtils;
import com.base.cn.platform.os.common.utils.action.ActionKey;
import com.base.cn.platform.os.dao.classes.topic.ClassesTopicDao;
import com.base.cn.platform.os.entity.classes.Classes;
import com.base.cn.platform.os.entity.classes.topic.ClassesTopic;
import com.base.cn.platform.os.entity.classes.topic.type.ClassesTopicType;
import com.base.cn.platform.os.service.classes.ClassesBiz;
import com.base.cn.platform.os.service.classes.member.ClassesMemberBiz;
import com.base.cn.platform.os.service.classes.topic.type.ClassesTopicTypeBiz;
import com.base.cn.platform.os.service.manage.user.integral.CusUserIntegralRecordService;
import com.base.cn.platform.os.service.manage.user.integral.CusUserIntegralService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 班级话题
 *
 * @author SK
 * @since 2018-05-15
 */
@Service
public class ClassesTopicBiz extends BaseBiz<ClassesTopic, ClassesTopicDao> {

    public static final int REPLY_NUM = 1;
    public static final int LIKE_NUM = 2;
    public static final int SHARE_NUM = 3;
    public static final int LOOK_NUM = 4;

    @Autowired
    private ClassesBiz classesBiz;
    @Autowired
    private ClassesMemberBiz classesMemberBiz;
    @Autowired
    private ClassesTopicDao classesTopicDao;
    @Autowired
    private ClassesTopicTypeBiz classesTopicTypeBiz;


    /**
     * 班级话题分类统计数量
     *
     * @param classesId 班级id
     * @return 班级话题分类统计数量
     */
    public Map<Integer, Long> classesTopicStatistics(BigDecimal classesId, BigDecimal userId) {
        List<Map<String, Number>> statistics = classesTopicDao.classesTopicStatistics(ClassesTopic.class, classesId, userId);
        if (ObjectUtils.isNotEmpty(statistics)) {
            Map<Integer, Long> result = new HashMap<>();
            statistics.forEach((v) -> result.put(v.get("classify").intValue(), v.get("count").longValue()));
            return result;
        }
        return Collections.emptyMap();
    }

    /**
     * 根据id查询班级话题
     *
     * @param id               试题id
     * @param setCreator       设置创建人
     * @param setClasses       设置班级
     * @param setTopicType     设置话题类型
     * @param updateStatistics 更新统计量
     * @return 班级话题
     */
    public ClassesTopic findClassesTopicById(BigDecimal id, boolean setCreator,
                                             boolean setClasses, boolean setTopicType,
                                             boolean updateStatistics) {
        ClassesTopic classesTopic = findById(id);
        if (updateStatistics) {
            this.updateClassesTopicStatistics(classesTopic, LOOK_NUM, 1);
        }
        this.setClassesTopicCreator(Collections.singletonList(classesTopic), setCreator);
        this.setClassesTopicClasses(Collections.singletonList(classesTopic), setClasses);
        this.setClassesTopicType(Collections.singletonList(classesTopic), setTopicType);
        return classesTopic;
    }

    /**
     * 根据ids查询班级话题
     *
     * @param ids 班级话题id
     * @return 班级话题 key:班级话题id value:班级话题
     */
    public Map<BigDecimal, ClassesTopic> findClassesTopicByIds(String ids, boolean setCreator,
                                                               boolean setClasses, boolean setTopicType) {
        List<ClassesTopic> classesTopicList = find(" id in (" + ids + ")", null, null);
        this.setClassesTopicCreator(classesTopicList, setCreator);
        this.setClassesTopicClasses(classesTopicList, setClasses);
        this.setClassesTopicType(classesTopicList, setTopicType);
        return DataUtil.toMap(classesTopicList, ClassesTopic::getId);
    }

    /**
     * 查询班级话题列表
     *
     * @param classesTopic 班级话题查询条件
     * @param setCreator   设置创建人
     * @param setClasses   设置班级
     * @param setTopicType 设置作业类型
     * @return 班级话题列表
     */
    public List<ClassesTopic> findClassesTopicList(ClassesTopic classesTopic, Integer count,
                                                   Integer order, boolean setCreator, boolean setClasses,
                                                   boolean setTopicType) {
        String where = this.where(classesTopic, order);
        List<ClassesTopic> classesTopicList = find(where, count, null);
        this.setClassesTopicClasses(classesTopicList, setClasses);
        this.setClassesTopicCreator(classesTopicList, setCreator);
        this.setClassesTopicType(classesTopicList, setTopicType);
        return classesTopicList;
    }

    /**
     * 查询班级话题列表
     *
     * @param classesTopic 班级话题查询条件
     * @param pagination   分页
     * @param setCreator   设置创建人
     * @param setClasses   设置班级
     * @param setTopicType 设置作业类型
     * @return 班级话题列表
     */
    public PageInfo<ClassesTopic> findClassesTopicListPage(ClassesTopic classesTopic, Pagination pagination,
                                                           Integer order, boolean setCreator, boolean setClasses,
                                                           boolean setTopicType) {
        String where = this.where(classesTopic, order);
        PageInfo<ClassesTopic> pageInfo = findPage(where, pagination, null);
        this.setClassesTopicClasses(pageInfo.getList(), setClasses);
        this.setClassesTopicCreator(pageInfo.getList(), setCreator);
        this.setClassesTopicType(pageInfo.getList(), setTopicType);
        //设置话题列表默认图片，适用于PC前台，话题列表
        boolean setTopicImage = ObjectUtils.isNotEmpty(classesTopic.getSource()) && classesTopic.getSource() == 1;
        this.setTopicDefaultImage(pageInfo.getList(),setTopicImage);
        return pageInfo;
    }

    /**
     * 查询班级话题列表
     *
     * @param userId       前台用户id
     * @param which        1.全部话题 2.发表的话题 3.参与的话题 4.转发的话题
     * @param setCreator   设置创建人
     * @param setClasses   设置班级
     * @param setTopicType 设置话题类型
     * @return 班级话题列表
     */
    public PageInfo<ClassesTopic> findClassesPersonalTopicPage(BigDecimal userId, Pagination pagination,
                                                               Integer which, boolean setCreator, boolean setClasses,
                                                               boolean setTopicType) {
        PageInfo<ClassesTopic> pageInfo = null;
        String where = " status = 1";
        switch (which) {
            case 1://1.全部话题
                pageInfo = this.findWebUserAllClassesTopicListPage(pagination,userId);
                break;
            case 2://2.发表的话题
                pageInfo = this.findWebUserPublishClassesTopicListPage(pagination,userId);
                break;
            case 3://3.参与的话题
                pageInfo = this.findWebUserReplyClassesTopicListPage(pagination,userId);
                break;
            case 4://4.转发的话题
                pageInfo = this.findWebUserShareClassesTopicListPage(pagination,userId);
                break;
        }
        if(pageInfo!=null){
            this.setClassesTopicClasses(pageInfo.getList(), setClasses);
            this.setClassesTopicCreator(pageInfo.getList(), setCreator);
            this.setClassesTopicType(pageInfo.getList(), setTopicType);
        }
        return pageInfo;
    }

    /**
     * 我的话题统计（发表话题量，参与回复的话题量）
     * @param userId 前台用户id
     * @return 我的话题统计
     */
    public Map<String, Object> classesPersonalTopicStatistics(@RequestParam("userId") BigDecimal userId) {
        Map<String,Object> dataMap = new HashMap<>();
        //查询用户发表的话题数量
        ClassesTopic condition = new ClassesTopic();
        condition.setCreateUserId(userId);
        condition.setSource(1);
        condition.setStatus(1);
        String where = this.where(condition, 0);
        BigDecimal publishCount = this.count(where);
        dataMap.put("publishCount",publishCount.longValue());
        long replyCount = this.findWebUserReplyClassesTopicCount(userId);
        dataMap.put("replyCount",replyCount);
        return dataMap;
    }

    /**
     * 保存班级话题
     *
     * @param classesTopic 班级话题
     */
    @Transactional(rollbackFor = Exception.class)
    public ClassesTopic saveClassesTopic(ClassesTopic classesTopic, String classesIds) {
        if (DataUtil.idIsNotNull(classesTopic.getId())) {
            ClassesTopic database = findById(classesTopic.getId());
            database.setTitle(classesTopic.getTitle());
            database.setContent(classesTopic.getContent());
            database.setTopicImages(classesTopic.getTopicImages());
            database.setLookPermission(classesTopic.getLookPermission());
            database.setReply(classesTopic.getReply());
            database.setTop(classesTopic.getTop());
            if(classesTopic.getReply() == 1){
                database.setReplyPermission(classesTopic.getReplyPermission());
            }
            if (database.getStatus() != 1) {
                database.setStatus(classesTopic.getStatus());
            }
            if (!DataUtil.idIsNotNull(database.getCreateUserId())) {
                database.setCreateUserId(classesTopic.getCreateUserId());
            }
            updateById(database, null);
            return database;
        } else {
            classesIds = DataUtil.filterNotNumberStr(classesIds);
            List<ClassesTopic> classesTopicList = Stream.of(classesIds.split(","))
                    .map((v) -> this.copy(classesTopic, v))
                    .collect(Collectors.toList());
            batchSave(classesTopicList);
            classesTopicTypeBiz.updateClassesTopicTypeNum(new BigDecimal(classesTopic.getClassify().toString()),1);
            if (classesTopicList.size() == 1) {
                classesTopic.setId(classesTopicList.get(0).getId());
            }
            Map<String, Integer> statisticsMap = Stream.of(classesIds.split(",")).collect(Collectors.toMap(Function.identity(), (v) -> 1));
            classesBiz.updateClassesStatistics(statisticsMap, ClassesStatisticsEnum.TOPIC_COUNT);
            return classesTopic;
        }
    }

    /**复制班级对象*/
    private ClassesTopic copy(ClassesTopic raw, String classesId) {
        ClassesTopic copy = new ClassesTopic();
        BeanUtils.copyProperties(raw, copy);
        copy.setClassesId(new BigDecimal(classesId));
        return copy;
    }

    /**
     * 更新班级话题统计数据
     *
     * @param topic      班级话题
     * @param statistics 统计
     * @param value      增加(减少)值
     */
    public void updateClassesTopicStatistics(ClassesTopic topic, int statistics, int value) {
        switch (statistics) {
            case REPLY_NUM:
                topic.setReplyNum(topic.getReplyNum() + value);
                break;
            case LIKE_NUM:
                topic.setLikeNum(topic.getLikeNum() + value);
                break;
            case LOOK_NUM:
                topic.setLookNum(topic.getLookNum() + value);
                break;
            case SHARE_NUM:
                topic.setShareNum(topic.getShareNum() + value);
                break;
            default:
                break;
        }
        updateById(topic, null);
    }

    /**
     * 更新班级话题状态
     *
     * @param ids    班级话题id
     * @param status 班级话题状态 0.未发布 1.已发布 2.已禁用 3.已删除
     */
    public void updateClassesTopicStatus(String ids, int status) {
        String where = " id in (" + ids + ")";
        ClassesTopic classesTopic = new ClassesTopic();
        classesTopic.setStatus(status);
        this.updateByWhereSql(classesTopic, where);
        if(status==3){
            List<ClassesTopic> topicList = this.find(where,null,null);
            String classesIds = topicList.stream().map(e -> e.getClassesId().toString()).collect(Collectors.joining(","));
            Map<String, Integer> statisticsMap = Stream.of(classesIds.split(",")).collect(Collectors.toMap(Function.identity(), (v) -> -1));
            classesBiz.updateClassesStatistics(statisticsMap, ClassesStatisticsEnum.TOPIC_COUNT);
            for( ClassesTopic topic:topicList){
                classesTopicTypeBiz.updateClassesTopicTypeNum(new BigDecimal(topic.getClassify()),-1);
            }
        }
    }

    /**
     * 更新班级话题状态
     *
     * @param ids 班级话题id
     * @param top 置顶 1.是 2.否
     */
    public void updateClassesTopicTop(String ids, int top) {
        String where = " id in (" + ids + ")";
        ClassesTopic classesTopic = new ClassesTopic();
        classesTopic.setTop(top);
        this.updateByWhereSql(classesTopic, where);
    }

    /**
     * 查询用户前台参与回复的话题数量
     * @param userId 用户ID
     * @return 数量
     */
    public Long findWebUserReplyClassesTopicCount(BigDecimal userId){
        return classesTopicDao.findWebUserReplyClassesTopicCount(ClassesTopic.class,userId);
    }

    /**
     * 查询用户前台发表的的话题数量
     * @param userId 用户ID
     * @return 数量
     */
    public Long findWebUserPublishClassesTopicCount(BigDecimal userId){
        return classesTopicDao.findWebUserPublishClassesTopicCount(ClassesTopic.class,userId);
    }

    //====================================================================================
    /**
     * 查询用户前台话题列表(全部的话题)
     * @param page 分页数据
     * @param userId 用户ID
     * @return 数据列表
     */
    private PageInfo<ClassesTopic> findWebUserAllClassesTopicListPage(Pagination page, BigDecimal userId){
        PageHelper.startPage(page.getCurrentPage(),page.getPageSize());
        Page<ClassesTopic> classesTopicPage = classesTopicDao.findWebUserAllClassesTopicListPage(ClassesTopic.class,userId);
        return new PageInfo<ClassesTopic>(classesTopicPage);
    }

    /**
     * 查询用户前台话题列表(发表的话题)
     * @param userId 用户ID
     * @return 数据列表
     */
    private PageInfo<ClassesTopic> findWebUserPublishClassesTopicListPage(Pagination page, BigDecimal userId){
        PageHelper.startPage(page.getCurrentPage(),page.getPageSize());
        Page<ClassesTopic> classesTopicPage = classesTopicDao.findWebUserPublishClassesTopicListPage(ClassesTopic.class,userId);
        return new PageInfo<ClassesTopic>(classesTopicPage);
    }


    /**
     * 查询用户前台话题列表(参与回复的话题)
     * @param userId 用户ID
     * @return 数据列表
     */
    private PageInfo<ClassesTopic> findWebUserReplyClassesTopicListPage(Pagination page, BigDecimal userId){
        PageHelper.startPage(page.getCurrentPage(),page.getPageSize());
        Page<ClassesTopic> classesTopicPage = classesTopicDao.findWebUserReplyClassesTopicListPage(ClassesTopic.class,userId);
        return new PageInfo<ClassesTopic>(classesTopicPage);
    }

    /**
     * 查询用户前台话题列表(分享的话题)
     * @param userId 用户ID
     * @return 数据列表
     */
    private PageInfo<ClassesTopic> findWebUserShareClassesTopicListPage(Pagination page, BigDecimal userId){
        PageHelper.startPage(page.getCurrentPage(),page.getPageSize());
        Page<ClassesTopic> classesTopicPage = classesTopicDao.findWebUserShareClassesTopicListPage(ClassesTopic.class,userId);
        return new PageInfo<ClassesTopic>(classesTopicPage);
    }

    /**
     * 设置话题关联班级
     *
     * @param classesTopicList 班级话题
     * @param setClasses       设置班级
     */
    private void setClassesTopicClasses(List<ClassesTopic> classesTopicList, boolean setClasses) {
        if (setClasses && ObjectUtils.isNotEmpty(classesTopicList)) {
            String classesIds = DataUtil.joining(classesTopicList, ClassesTopic::getClassesId);
            if (StringUtils.isNotEmpty(classesIds)) {
                Map<BigDecimal, Classes> classesMap = classesBiz.findClassesByIds(classesIds, false, false);
                classesTopicList.forEach((v) -> v.setClasses(classesMap.get(v.getClassesId())));
            }
        }
    }

    /**
     * 设置话题创建人
     *
     * @param classesTopicList 班级话题
     * @param setCreator       设置创建人
     */
    private void setClassesTopicCreator(List<ClassesTopic> classesTopicList, boolean setCreator) {
        if (setCreator && ObjectUtils.isNotEmpty(classesTopicList)) {
            Map<Integer, List<ClassesTopic>> classesTopicMap = DataUtil.grouping(classesTopicList, ClassesTopic::getSource);
            String cusUserIds = DataUtil.joining(classesTopicMap.get(1), ClassesTopic::getCreateUserId);
            String sysUserIds = DataUtil.joining(classesTopicMap.get(2), ClassesTopic::getCreateUserId);
            String teacherIds = DataUtil.joining(classesTopicMap.get(3), ClassesTopic::getCreateUserId);
            Map<BigDecimal, Map<String, Object>> cusUserMap = classesMemberBiz.getCusUserMap(cusUserIds);
            Map<BigDecimal, Map<String, Object>> sysUserMap = classesMemberBiz.getSysUserMap(sysUserIds);
            Map<BigDecimal, Map<String, Object>> teacherMap = classesMemberBiz.getTeacherMap(teacherIds);
            for (ClassesTopic classesTopic :classesTopicList){
                switch (classesTopic.getSource()){
                    case  1:
                        classesTopic.setCreateUser(cusUserMap.get(classesTopic.getCreateUserId()));
                        break;
                    case 2:
                        classesTopic.setCreateUser(sysUserMap.get(classesTopic.getCreateUserId()));
                        break;
                    case 3:
                        classesTopic.setCreateUser(teacherMap.get(classesTopic.getCreateUserId()));
                        break;
                }
                dealWithNameAndImg(classesTopic);
            }
        }
    }

    /**
     * 设置话题类型
     *
     * @param classesTopicList 班级话题
     * @param setTopicType     设置话题类型
     */
    private void setClassesTopicType(List<ClassesTopic> classesTopicList, boolean setTopicType) {
        if (setTopicType && ObjectUtils.isNotEmpty(classesTopicList)) {
            List<ClassesTopicType> classesTopicTypes = classesTopicTypeBiz.find("", null, null);
            Map<BigDecimal, ClassesTopicType> collect = classesTopicTypes.stream().collect(Collectors.toMap(ClassesTopicType::getId,e->e));
            classesTopicList.forEach((v) -> v.setTopicTypeName(ObjectUtils.isNotEmpty(collect.get(new BigDecimal(v.getClassify())))?collect.get(new BigDecimal(v.getClassify())).getName():""));
        }
    }

    /**
     * 设置话题默认图片
     * @param classesTopicList 班级话题
     * @param setTopicImage     设置话题类型
     */
    private void setTopicDefaultImage(List<ClassesTopic> classesTopicList, boolean setTopicImage){
        if(ObjectUtils.isNotEmpty(classesTopicList) && setTopicImage){
            classesTopicList.stream().forEach(e -> {
                String topicImages = e.getTopicImages();
                if(StringUtils.isNotEmpty(topicImages)){
                    String topicImage = topicImages.split(",")[0];
                    e.setTopicImage(topicImage);
                }
            });
        }
    }

    /**
     * 拼接where子句
     *
     * @param classesTopic 班级话题
     * @return where子句
     */
    private String where(ClassesTopic classesTopic, Integer order) {
        StringBuilder where = new StringBuilder(" status != 3");
        if (DataUtil.idIsNotNull(classesTopic.getClassesId())) {
            where.append(" and classesId = ").append(classesTopic.getClassesId());
        }
        if (DataUtil.isPositive(classesTopic.getClassify())) {
            where.append(" and classify = ").append(classesTopic.getClassify());
        }
        if (StringUtils.isNotEmpty(classesTopic.getTitle())) {
            where.append(" and title like '%" ).append( classesTopic.getTitle()).append("%'");
        }
        if (StringUtils.isNotEmpty(classesTopic.getContent())) {
            where.append(" and content like '%" ).append(classesTopic.getContent() ).append( "%'");
        }
        if (DataUtil.isNonNegative(classesTopic.getStatus())) {
            where.append(" and status = ").append(classesTopic.getStatus());
        }
        if (DataUtil.idIsNotNull(classesTopic.getCreateUserId())) {
            where.append(" and createUserId = ").append(classesTopic.getCreateUserId());
        }
        if (DataUtil.isPositive(classesTopic.getSource())) {
            where.append(" and source = ").append(classesTopic.getSource());
        }
        if(StringUtils.isNotEmpty(classesTopic.getClassIds())){
            where.append(" and classesId in (").append(classesTopic.getClassIds()).append(")");
        }
        Boolean joined = classesTopic.getJoined();
        if(ObjectUtils.isNotEmpty(joined)){
            if(!joined){
                if(DataUtil.idIsNotNull(classesTopic.getUserId())){
                    where.append(" and lookPermission != 3");
                }else {
                    where.append(" and lookPermission = 1");
                }
            }
        }
        if (DataUtil.isPositive(order)) {
            where.append(" order by ").append (order == 1 ? " createTime desc" : " lookNum desc");
        }else{
            where.append(" order by id desc");
        }
        return where.toString();

    }


    /**
     * 处理话题名字与图片
     * @param classesTopic
     */
    private    static void  dealWithNameAndImg( ClassesTopic classesTopic){
        if(ObjectUtils.isNotEmpty(classesTopic)){
            dealWithName(classesTopic.getCreateUser(),classesTopic.getSource());
            dealWithImg(classesTopic.getCreateUser());

        }
    }

    /**
     * 处理名字
     * @param createUser
     * @param source
     */
    private static void  dealWithName(Map<String, Object> createUser,Integer source){
        switch (source){
            case 2:
                createUser.put("nickname",createUser.get("ralName").toString());
                break;
            case 3:
                if(createUser != null){
                    createUser.put("nickname", createUser.get("teacherName").toString());
                }
                break;
        }
    }

    /**
     * 处理图片
     * @param createUser
     */
    private static void dealWithImg(Map<String, Object> createUser) {
        if (ObjectUtils.isNotEmpty(createUser)) {
            Object avatar = createUser.get("avatar");
            if (ObjectUtils.isEmpty(avatar)) {
                Map<String, Object> imageMap = (Map<String, Object>) createUser.get("imageMap");
                if (ObjectUtils.isNotEmpty(imageMap)) {
                    imageMap = (Map<String, Object>) imageMap.get("mobileUrlMap");
                    if (ObjectUtils.isNotEmpty(imageMap)) {
                        createUser.put("avatar", imageMap.get("large"));
                    }
                }
            }
        }
    }

    /**
     * 查询话题数量
     * @param classesTopic 查询条件
     * @return  BigDecimal
     */
    public BigDecimal getClassTopicCount(ClassesTopic classesTopic){
        BigDecimal count = this.count(this.where(classesTopic,0));
        if(!DataUtil.idIsNotNull(count)){
            count = BigDecimal.ZERO;
        }
        return count;
    }
}
